home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / ada / gnat-3.05- / gnat-3 / gnat-3.05-i486-linux-elf-bin / rts / a-numran.adb < prev    next >
Encoding:
Text File  |  1996-06-07  |  8.5 KB  |  267 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT RUNTIME COMPONENTS                          --
  4. --                                                                          --
  5. --                  A D A . N U M E R I C S . R A N D O M                   --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.5 $                              --
  10. --                                                                          --
  11. --     Copyright (C) 1992,1993,1994,1995 Free Software Foundation, Inc.     --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
  22. -- MA 02111-1307, USA.                                                      --
  23. --                                                                          --
  24. -- As a special exception,  if other files  instantiate  generics from this --
  25. -- unit, or you link  this unit with other files  to produce an executable, --
  26. -- this  unit  does not  by itself cause  the resulting  executable  to  be --
  27. -- covered  by the  GNU  General  Public  License.  This exception does not --
  28. -- however invalidate  any other reasons why  the executable file  might be --
  29. -- covered by the  GNU Public License.                                      --
  30. --                                                                          --
  31. -- GNAT was originally developed  by the GNAT team at  New York University. --
  32. -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
  33. --                                                                          --
  34. ------------------------------------------------------------------------------
  35.  
  36. --  This implementation is derived from LSN 1055 written by Ken Dritz.
  37.  
  38. with Ada.Calendar;
  39.  
  40. package body Ada.Numerics.Random is
  41.  
  42.    ------------------------------
  43.    -- Form of the Image String --
  44.    ------------------------------
  45.  
  46.    --  The image string is of the form:
  47.  
  48.    --     nnn,nnn,nnn .... nnn,b
  49.  
  50.    --  There are Larger_Lag nnn components, where each component is a
  51.    --  decimal integer representing the values of the Lagged_Outputs in
  52.    --  the State_Vector, stored as rounded values * 2**24, in reverse order
  53.    --  (i.e. highest indexed value comes first), b is the borrow (0/1)
  54.  
  55.    -----------
  56.    -- Image --
  57.    -----------
  58.  
  59.    function Image (S : State) return String is
  60.       Result        : String (1 .. Max_Image_Width);
  61.       Result_Length : Natural;
  62.  
  63.       procedure Encode (Value : Float);
  64.       --  Add encoded float value to result string, using the float value
  65.       --  multiplied by 2**24 as a rounded decimal integer string.
  66.  
  67.       procedure Encode (Value : Float) is
  68.          Img : constant String := Int'Image (Int (2#1.0#E24 * Value));
  69.  
  70.       begin
  71.          for J in 2 .. Img'Length loop
  72.             Result_Length := Result_Length + 1;
  73.             Result (Result_Length) := Img (J);
  74.          end loop;
  75.       end Encode;
  76.  
  77.    --  Start processing for Image
  78.  
  79.    begin
  80.       Result_Length := 0;
  81.  
  82.       for J in Lag_Range loop
  83.          Encode (S.Lagged_Outputs (S.R - J));
  84.          Result_Length := Result_Length + 1;
  85.          Result (Result_Length) := ',';
  86.       end loop;
  87.  
  88.       Encode (S.Borrow);
  89.       return Result (1 .. Result_Length);
  90.    end Image;
  91.  
  92.    ----------------
  93.    -- Make_State --
  94.    ----------------
  95.  
  96.    function Make_State (Starter : Int := 3E+7) return State is
  97.       Bit_Value      : Float;
  98.       LCG_State      : Float;
  99.  
  100.       Result : State;
  101.  
  102.       function LCG_Random return Uniformly_Distributed;
  103.       --  Needs comments???
  104.  
  105.       function LCG_Random return Uniformly_Distributed is
  106.          LCG_Multiplier : constant := 16_807.0;
  107.          LCG_Modulus    : constant := 2_147_483_647.0;
  108.          T : Float;
  109.          J : Int;
  110.  
  111.       begin
  112.          T := LCG_State * LCG_Multiplier;
  113.          J := Int (T / LCG_Modulus);
  114.          LCG_State := T - Float (J) * LCG_Modulus;
  115.  
  116.          if LCG_State < 0.0 then
  117.             LCG_State := LCG_State + LCG_Modulus;
  118.          end if;
  119.  
  120.          return LCG_State / LCG_Modulus;
  121.       end LCG_Random;
  122.  
  123.    --  Start of processing for Make_State
  124.  
  125.    begin
  126.       LCG_State := Float (Starter);
  127.  
  128.       for J in Lag_Range loop
  129.          Result.Lagged_Outputs (J) := 0.0;
  130.          Bit_Value := 1.0;
  131.  
  132.          for K in 1 .. 24 loop
  133.             Bit_Value := Bit_Value * 0.5;
  134.  
  135.             if LCG_Random >= 0.5 then
  136.                Result.Lagged_Outputs (J) :=
  137.                  Result.Lagged_Outputs (J) + Bit_Value;
  138.             end if;
  139.          end loop;
  140.       end loop;
  141.  
  142.       Result.Borrow := 0.0;
  143.       Result.R      := Lag_Range'Last;
  144.       Result.S      := Smaller_Lag - 1;
  145.       return Result;
  146.    end Make_State;
  147.  
  148.    ------------
  149.    -- Random --
  150.    ------------
  151.  
  152.    procedure Random (S : in out State; U : out Uniformly_Distributed) is
  153.       U1 : Uniformly_Distributed'Base;
  154.    begin
  155.       U1 := S.Lagged_Outputs (S.R) - S.Lagged_Outputs (S.S) - S.Borrow;
  156.  
  157.       if U1 < 0.0 then
  158.          U1 := U1 + 1.0;
  159.          S.Borrow := 2#1.0#e-24;
  160.       else
  161.          S.Borrow := 0.0;
  162.       end if;
  163.  
  164.       U := U1;
  165.       S.Lagged_Outputs (S.R) := U;
  166.       S.R := S.R - 1;
  167.       S.S := S.S - 1;
  168.    end Random;
  169.  
  170.    -----------
  171.    -- Reset --
  172.    -----------
  173.  
  174.    procedure Reset (S : out State; Initiator : in Integer) is
  175.    begin
  176.       S := Make_State (Int (Initiator) mod 2_147_483_646 + 1);
  177.    end Reset;
  178.  
  179.    procedure Reset (S : out State) is
  180.       use Ada.Calendar;
  181.  
  182.       Year  : Year_Number;
  183.       Month : Month_Number;
  184.       Day   : Day_Number;
  185.       Secs  : Day_Duration;
  186.  
  187.    begin
  188.       Split (Clock, Year, Month, Day, Secs);
  189.       S := Make_State (((Int (Year)   * 12 +
  190.                          Int (Month)) * 32 +
  191.                          Int (Day))   * 24 * 60 * 60 +
  192.                          Int (Secs));
  193.    end Reset;
  194.  
  195.    -----------
  196.    -- Value --
  197.    -----------
  198.  
  199.    function Value (S : String) return State is
  200.       Result : State;
  201.       Ptr    : Natural := S'First;
  202.  
  203.       function Decode_Component (Max : in Nat) return Float;
  204.       --  Decode next component as a floating-point value, by reading an
  205.       --  integer up to a comma or the end of the string, and converting
  206.       --  it to float by dividing by 2**24. Ptr is the initial location for
  207.       --  the scan, and is advanced past the termninator. Max is the maximum
  208.       --  value of the component as an integer (2**24 - 1 for the lagged
  209.       --  components, and 1 for the borrow).
  210.  
  211.       function Decode_Component (Max : in Nat) return Float is
  212.          End_Ptr : Natural;
  213.          Int_Val : Nat;
  214.  
  215.       begin
  216.          --  Not enough components if past end of string
  217.  
  218.          if Ptr > S'Last then
  219.             raise Constraint_Error;
  220.          end if;
  221.  
  222.          End_Ptr := Ptr;
  223.  
  224.          while End_Ptr <= S'Last
  225.            and then S (End_Ptr) /= ','
  226.          loop
  227.             End_Ptr := End_Ptr + 1;
  228.          end loop;
  229.  
  230.          --  Make sure Length is in reasonable bounds (2**24 < 10**8)
  231.  
  232.          if End_Ptr = Ptr or else End_Ptr > Ptr + 8 then
  233.             raise Constraint_Error;
  234.          end if;
  235.  
  236.          Int_Val := Nat'Value (S (Ptr .. End_Ptr - 1));
  237.  
  238.          if Int_Val > Max then
  239.             raise Constraint_Error;
  240.          end if;
  241.  
  242.          Ptr := End_Ptr;
  243.          return Float (Int_Val) * 2#1.0#e-24;
  244.       end Decode_Component;
  245.  
  246.    --  Start of processing for Value
  247.  
  248.    begin
  249.       for J in reverse Lag_Range loop
  250.          Result.Lagged_Outputs (J) := Decode_Component (2**24 - 1);
  251.       end loop;
  252.  
  253.       Result.Borrow := Decode_Component (1);
  254.  
  255.       --  Must be at end of string now!
  256.  
  257.       if Ptr <= S'Last then
  258.          raise Constraint_Error;
  259.       end if;
  260.  
  261.       Result.R := Lag_Range'Last;
  262.       Result.S := Smaller_Lag - 1;
  263.       return Result;
  264.    end Value;
  265.  
  266. end Ada.Numerics.Random;
  267.